package com.sunfeng.two.p2;

import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;
import util.ConnectionUtil;

import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * @Author : 清风冷影
 * @Description:
 *      消息应答模式  为了保证消息的发送的工程中不丢失 rabbitmq 引入消息应答机制  消息应答就是:消费者在接到消息并处理后告诉rabbitmq消息已经被处理了 rabbitmq可以删除消息了
 * *
 * *
 * * A.Channel.basicAck(用于肯定确认) RabbitMQ 已知道该消息并且成功的处理消息，可以将其丢弃了
 * * B.Channel.basicNack(用于否定确认)
 * * C.Channel.basicReject(用于否定确认) 与 Channel.basicNack 相比少一个参数不处理该消息了直接拒绝，可以将其丢弃了
 *  Multiple 的解释
 *      true 代表批量应答 channel 上未应答的消息
 *          比如说 channel 上有传送 tag 的消息 5,6,7,8 当前 tag 是 8 那么此时5-8 的这些还未应答的消息都会被确认收到消息应答
 *      false 同上面相比
 *          只会应答 tag=8 的消息 5,6,7 这三个消息依然不会被确认收到消息应答
 *
 *  消息自动重新入队
 *  如果消费者由于某些原因失去连接(其通道已关闭，连接已关闭或 TCP 连接丢失)，导致消息未发送 ACK 确认，RabbitMQ 将了解到消息未完全处理，并将对其重新排队。
 *  如果此时其他消费者可以处理，它将很快将其重新分发给另一个消费者。
 *
 *
 * @Date : 2021/8/20  13:54
 */
public class Worker02 {

    private static final String TASK_QUEUE_NAME = "ack_queue";

    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        final Channel channel = ConnectionUtil.getChannel();
          channel.basicQos(1);// 设置客户端最多接收未被 ack 的消息的个数
        System.out.println("C1 等待接受消息处理时间比较短的");
        DeliverCallback deliverCallback = (consumerTag, message) -> {
            try {
                TimeUnit.SECONDS.sleep(1);
                System.out.println(" 接受到消息: " + new String(message.getBody()));
                /**
                 * 1 消息的标识
                 * 2 是否批量确认 批量确认
                 */

                channel.basicAck(message.getEnvelope().getDeliveryTag(), false);
                /**
                 * 1 消息的标识
                 * 2 是否批量确认 批量确认
                 * 3 是否重新入队    保证单个消费者消费失败 不会造成消息丢失
                 */
                // channel.basicNack(message.getEnvelope().getDeliveryTag(),false,false);
                //   channel.basicReject(message.getEnvelope().getDeliveryTag(), false);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        };


        //autoAck设置为false 可以防止消息不必要的丢失   建议设置为false
        channel.basicConsume(TASK_QUEUE_NAME, false, deliverCallback, consumerTag -> {
            System.out.println("aaaaaaa");
        });

    }
}
